home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 38 / Amiga Format CD38 (1999-03-15)(Future Publishing)(GB)(Track 1 of 3)[!][issue 1999-04].iso / -seriously_amiga- / programming / other / cyberxxxsrc / cyberqt / txt / cyberqtaudio.mod < prev    next >
Text File  |  1999-02-08  |  29KB  |  816 lines

  1. MODULE  CyberQTAudio;
  2.  
  3. (* $IFNOT DEBUG *)
  4.   (* $StackChk- $OvflChk- $RangeChk- $CaseChk- $ReturnChk- $NilChk- $TypeChk- $OddChk- $ClearVars- *)
  5. (* $END *)
  6.  
  7. (* /// ------------------------------- "IMPORT" -------------------------------- *)
  8. IMPORT  au:=Audio,
  9.         aus:=AudioSupport,
  10.         cu:=CyberQTUtils,
  11.         d:=Dos,
  12.         e:=Exec,
  13.         es:=ExecSupport,
  14.         els:=ExecListSupport,
  15.         fp:=FixedPoint,
  16.         g:=CyberQTGlobals,
  17.         i2m:=Intel2Mot,
  18.         io:=AsyncIOSupport2,
  19.         mu:=MathUtils,
  20.         o:=CyberQTOpts,
  21.         ol:=OberonLib,
  22.         s:=CyberQTSync,
  23.         u:=Utility,
  24.         v:=CyberQTVideo,
  25.         y:=SYSTEM;
  26. (* \\\ ------------------------------------------------------------------------- *)
  27.  
  28. (* /// -------------------------------- "TYPE" --------------------------------- *)
  29. TYPE    CommonDataPtr=UNTRACED POINTER TO CommonData;
  30.         CommonData=STRUCT
  31.             downScale: BOOLEAN;
  32.         END;
  33.  
  34.         DecoderProc=PROCEDURE(from{8}: e.APTR;
  35.                               toL{9}: e.APTR;
  36.                               toR{10}: e.APTR;
  37.                               size{0}: LONGINT;
  38.                               spec{11}: CommonDataPtr): LONGINT;
  39.  
  40.         CodecHeader=STRUCT
  41.             decoder: DecoderProc;
  42.             special: CommonDataPtr;
  43.             frequency: LONGINT;
  44.             compression: LONGINT;
  45.             channels: INTEGER;
  46.             bits: INTEGER;
  47.             stereo: BOOLEAN;
  48.             realCompression: BOOLEAN;
  49.             compressFactor: REAL;
  50.             description: e.STRING;
  51.         END;
  52.  
  53.         CodecArray=UNTRACED POINTER TO ARRAY MAX(INTEGER) OF CodecHeader;
  54.  
  55.         SampleNodePtr=UNTRACED POINTER TO SampleNode;
  56.         SampleNode=STRUCT (node: e.MinNode)
  57.             freq: LONGINT;
  58.             dataL: e.LSTRPTR;
  59.             dataR: e.LSTRPTR;
  60.             size: LONGINT;
  61.             done: LONGINT;
  62.             id: LONGINT;
  63.         END;
  64. (* \\\ ------------------------------------------------------------------------- *)
  65.  
  66. (* /// -------------------------------- "CONST" -------------------------------- *)
  67. CONST   idraw =y.VAL(LONGINT,"raw ");
  68.         idraw0=0;
  69.         idtwos=y.VAL(LONGINT,"twos");
  70.         idMAC3=y.VAL(LONGINT,"MAC3");
  71.         idMAC6=y.VAL(LONGINT,"MAC6");
  72.         idima4=y.VAL(LONGINT,"ima4");
  73.         idulaw=y.VAL(LONGINT,"µlaw");
  74.  
  75.         codecSupported * =1;
  76.         codecUnknown * =0;
  77.         codecUnsupported * =-1;
  78.  
  79.         maxAudioHWSize=131072;
  80. (* \\\ ------------------------------------------------------------------------- *)
  81.  
  82. (* /// --------------------------------- "VAR" --------------------------------- *)
  83. VAR     audioFile: io.ASFile;
  84.         mainData: e.LSTRPTR;
  85.         mainPort: e.MsgPortPtr;
  86.         mainIO: au.IOAudioPtr;
  87.         leftData: ARRAY 2 OF e.LSTRPTR;
  88.         leftPort: ARRAY 2 OF e.MsgPortPtr;
  89.         leftIO: ARRAY 2 OF au.IOAudioPtr;
  90.         rightData: ARRAY 2 OF e.LSTRPTR;
  91.         rightPort: ARRAY 2 OF e.MsgPortPtr;
  92.         rightIO: ARRAY 2 OF au.IOAudioPtr;
  93.         audioOpen - : BOOLEAN;
  94.         decoderProc: DecoderProc;
  95.         decoderSpec: e.APTR;
  96.         audioFreq: LONGINT;
  97.         audioBufferSize - : LONGINT;
  98.         currSample: SHORTINT;
  99.         playing: BOOLEAN;
  100.         bufPlaying: ARRAY 2 OF BOOLEAN;
  101.         stereo: BOOLEAN;
  102.         splittedStereo - : BOOLEAN;
  103.         sampleSize: LONGINT;
  104.         codecs: CodecArray;
  105.         codecCnt: LONGINT;
  106.         currentCodec: LONGINT;
  107.         audioSizeScale: LONGINT;
  108.         sampleQueue: els.Queue;
  109.         audioSigs - : LONGSET;
  110.         (* fh: d.FileHandlePtr; *)
  111. (* \\\ ------------------------------------------------------------------------- *)
  112.  
  113. (* /// --------------------- "PROCEDURE FlushQueueFunc()" ---------------------- *)
  114. PROCEDURE FlushQueueFunc(n: e.CommonNodePtr);
  115. BEGIN
  116.   DISPOSE(n(SampleNodePtr).dataL);
  117.   DISPOSE(n(SampleNodePtr).dataR);
  118.   DISPOSE(n);
  119. END FlushQueueFunc;
  120. (* \\\ ------------------------------------------------------------------------- *)
  121.  
  122. (* /// ----------------------- "PROCEDURE CloseAudio()" ------------------------ *)
  123. PROCEDURE CloseAudio();
  124.  
  125. VAR     cnt: INTEGER;
  126.  
  127. BEGIN
  128.   els.Flush(sampleQueue,FlushQueueFunc);
  129.   IF audioOpen THEN e.CloseDevice(mainIO); audioOpen:=FALSE; END;
  130.   IF mainIO#NIL THEN e.DeleteIORequest(mainIO); mainIO:=NIL; END;
  131.   IF mainPort#NIL THEN e.DeleteMsgPort(mainPort); mainPort:=NIL; END;
  132.   FOR cnt:=0 TO 1 DO
  133.     IF leftIO[cnt]#NIL THEN e.DeleteIORequest(leftIO[cnt]); leftIO[cnt]:=NIL; END;
  134.     IF rightIO[cnt]#NIL THEN e.DeleteIORequest(rightIO[cnt]); rightIO[cnt]:=NIL; END;
  135.     IF leftPort[cnt]#NIL THEN e.DeleteMsgPort(leftPort[cnt]); leftPort[cnt]:=NIL; END;
  136.     IF rightPort[cnt]#NIL THEN e.DeleteMsgPort(rightPort[cnt]); rightPort[cnt]:=NIL; END;
  137.   END;
  138. END CloseAudio;
  139. (* \\\ ------------------------------------------------------------------------- *)
  140.  
  141. (* /// ------------------------ "PROCEDURE OpenAudio()" ------------------------ *)
  142. PROCEDURE OpenAudio();
  143.  
  144. VAR     cnt: INTEGER;
  145.  
  146. BEGIN
  147.   playing:=FALSE;
  148.   bufPlaying[0]:=FALSE;
  149.   bufPlaying[1]:=FALSE;
  150.   currSample:=0;
  151.   es.NewList(sampleQueue);
  152.   mainPort:=e.CreateMsgPort();
  153.   IF mainPort=NIL THEN
  154.     d.PrintF("Can't create audio message port!\n");
  155.     CloseAudio();
  156.   END;
  157.   mainIO:=e.CreateIORequest(mainPort,SIZE(mainIO^));
  158.   IF mainIO=NIL THEN
  159.     d.PrintF("Can't create audio iorequest!\n");
  160.     CloseAudio();
  161.   END;
  162.  
  163.   FOR cnt:=0 TO 1 DO
  164.     leftPort[cnt]:=e.CreateMsgPort();
  165.     rightPort[cnt]:=e.CreateMsgPort();
  166.     IF (leftPort[cnt]=NIL) OR (rightPort[cnt]=NIL) THEN
  167.       d.PrintF("Can't create audio message port!\n");
  168.       CloseAudio();
  169.     END;
  170.     leftIO[cnt]:=e.CreateIORequest(leftPort[cnt],SIZE(leftIO[cnt]^));
  171.     rightIO[cnt]:=e.CreateIORequest(rightPort[cnt],SIZE(rightIO[cnt]^));
  172.     IF (leftIO[cnt]=NIL) OR (rightIO[cnt]=NIL) THEN
  173.       d.PrintF("Can't create audio iorequest!\n");
  174.       CloseAudio();
  175.     END;
  176.   END;
  177.   mainIO.request.message.node.pri:=au.allocMaxprec;
  178.   mainIO.data:=y.ADR(aus.channelMap);
  179.   mainIO.length:=aus.channelSize;
  180.   audioOpen:=(e.OpenDevice(au.audioName,0,mainIO,LONGSET{})=0);
  181.   IF ~audioOpen THEN
  182.     d.PrintF("Can't open audio.device!\n");
  183.     CloseAudio();
  184.   ELSE
  185.     aus.CopyUnit(mainIO,leftIO[0],aus.leftOnly);
  186.     aus.CopyUnit(mainIO,leftIO[1],aus.leftOnly);
  187.     aus.CopyUnit(mainIO,rightIO[0],aus.rightOnly);
  188.     aus.CopyUnit(mainIO,rightIO[1],aus.rightOnly);
  189.     aus.ResetAudio(mainIO);
  190.     aus.StopAudio(mainIO);
  191.   END;
  192. END OpenAudio;
  193. (* \\\ ------------------------------------------------------------------------- *)
  194.  
  195. (* /// ----------------------- "PROCEDURE PlaySample()" ------------------------ *)
  196. PROCEDURE PlaySample * (forceWait: BOOLEAN);
  197.  
  198. VAR     node: SampleNodePtr;
  199.         freq: LONGINT;
  200.         dataL: e.LSTRPTR;
  201.         dataR: e.LSTRPTR;
  202.         size: LONGINT;
  203.         offset: LONGINT;
  204.         reUse: BOOLEAN;
  205.  
  206. BEGIN
  207.   IF ~playing THEN RETURN; END;
  208.   IF bufPlaying[currSample] THEN
  209.     IF s.speedChanged THEN
  210.       IF e.CheckIO(leftIO[currSample])=NIL THEN e.AbortIO(leftIO[currSample]); END;
  211.       IF e.CheckIO(rightIO[currSample])=NIL THEN e.AbortIO(rightIO[currSample]); END;
  212.     ELSIF ~forceWait THEN
  213.       (* d.PrintF("check %ld\n",currSample); *)
  214.       IF (e.CheckIO(leftIO[currSample])=NIL) OR (e.CheckIO(rightIO[currSample])=NIL) THEN (* d.PrintF("still playing\n"); *) RETURN; END; (* Sample wird noch gespielt *)
  215.       (* d.PrintF("wait %ld\n",currSample); *)
  216.     END;
  217.     y.SETREG(0,e.WaitIO(leftIO[currSample]));
  218.     y.SETREG(0,e.WaitIO(rightIO[currSample]));
  219.   END;
  220.   node:=els.First(sampleQueue);
  221.   IF node#NIL THEN
  222.     freq:=node.freq;
  223.     size:=node.size;
  224.     offset:=node.done;
  225.     (* d.PrintF("rem: %08lx, %7ld, %7ld, %8ld\n",node,size,offset,node.id); *)
  226.     reUse:=FALSE;
  227.     IF size>maxAudioHWSize THEN
  228.       IF offset+maxAudioHWSize<size THEN
  229.         size:=maxAudioHWSize;
  230.         reUse:=TRUE;
  231.       ELSE
  232.         size:=size-offset;
  233.       END;
  234.     END;
  235.     dataL:=leftData[currSample];
  236.     e.CopyMemAPTR(y.ADR(node.dataL[offset]),dataL,size);
  237.     IF stereo OR splittedStereo THEN
  238.       dataR:=rightData[currSample];
  239.       e.CopyMemAPTR(y.ADR(node.dataR[offset]),dataR,size);
  240.     ELSE
  241.       dataR:=dataL;
  242.     END;
  243.     aus.WriteAudio(leftIO[currSample],dataL,size,freq,64);
  244.     aus.WriteAudio(rightIO[currSample],dataR,size,freq,64);
  245.     bufPlaying[currSample]:=TRUE;
  246.     currSample:=1-currSample;
  247.     audioSigs:=LONGSET{leftPort[currSample].sigBit,rightPort[currSample].sigBit};
  248.     IF reUse THEN
  249.       INC(node.done,maxAudioHWSize);
  250.     ELSIF o.audioPreload & o.doLoop THEN
  251.       node.done:=0;
  252.       y.SETREG(0,els.Dequeue(sampleQueue));
  253.       els.Enqueue(sampleQueue,node);
  254.     ELSE
  255.       y.SETREG(0,els.Dequeue(sampleQueue));
  256.       FlushQueueFunc(node);
  257.     END;
  258.   END;
  259. END PlaySample;
  260. (* \\\ ------------------------------------------------------------------------- *)
  261.  
  262. (* /// --------------------- "PROCEDURE Wait4LastSample()" --------------------- *)
  263. PROCEDURE Wait4LastSample * (aborted: BOOLEAN);
  264. BEGIN
  265.   IF ~aborted THEN
  266.     WHILE ~es.ListEmpty(sampleQueue) DO PlaySample(~s.speedChanged); END;
  267.   END;
  268. END Wait4LastSample;
  269. (* \\\ ------------------------------------------------------------------------- *)
  270.  
  271. (* /// ----------------------- "PROCEDURE StartSound()" ------------------------ *)
  272. PROCEDURE StartSound * ();
  273. BEGIN
  274.   IF ~playing THEN
  275.     (* d.PrintF("start\n"); *)
  276.     playing:=TRUE;
  277.     IF ~bufPlaying[0] THEN PlaySample(FALSE); END;
  278.     IF bufPlaying[0] THEN
  279. (* /// "$IF RUNDEBUG" *)
  280.       IF o.debug THEN d.PrintF("starting audio\n"); END;
  281. (* \\\ $END *)
  282.       aus.StartAudio(mainIO);
  283.     ELSE
  284.       playing:=FALSE;
  285.     END;
  286.   END;
  287. END StartSound;
  288. (* \\\ ------------------------------------------------------------------------- *)
  289.  
  290. (* /// ------------------------ "PROCEDURE StopSound()" ------------------------ *)
  291. PROCEDURE StopSound * (aborted: BOOLEAN);
  292. BEGIN
  293.   (* IF es.ListEmpty(sampleQueue) THEN d.PrintF("empty\n"); END; *)
  294.   IF playing THEN
  295.     IF ~aborted & ~s.speedChanged THEN
  296.       y.SETREG(0,e.Wait(LONGSET{leftPort[1-currSample].sigBit}));
  297.       y.SETREG(0,e.Wait(LONGSET{rightPort[1-currSample].sigBit}));
  298.     END;
  299.     IF bufPlaying[1-currSample] THEN
  300.       WHILE e.CheckIO(leftIO[1-currSample])=NIL DO e.AbortIO(leftIO[1-currSample]); END;
  301.       y.SETREG(0,e.WaitIO(leftIO[1-currSample]));
  302.       WHILE e.CheckIO(rightIO[1-currSample])=NIL DO e.AbortIO(rightIO[1-currSample]); END;
  303.       y.SETREG(0,e.WaitIO(rightIO[1-currSample]));
  304.     END;
  305.     IF bufPlaying[currSample] THEN
  306.       WHILE e.CheckIO(leftIO[currSample])=NIL DO e.AbortIO(leftIO[currSample]); END;
  307.       y.SETREG(0,e.WaitIO(leftIO[currSample]));
  308.       WHILE e.CheckIO(rightIO[currSample])=NIL DO e.AbortIO(rightIO[currSample]); END;
  309.       y.SETREG(0,e.WaitIO(rightIO[currSample]));
  310.     END;
  311.     aus.StopAudio(mainIO);
  312.   END;
  313.   playing:=FALSE;
  314.   bufPlaying[0]:=FALSE;
  315.   bufPlaying[1]:=FALSE;
  316.   currSample:=0;
  317.   CloseAudio();
  318.   OpenAudio();
  319. END StopSound;
  320. (* \\\ ------------------------------------------------------------------------- *)
  321.  
  322. (* /// ----------------------- "PROCEDURE PauseSound()" ------------------------ *)
  323. PROCEDURE PauseSound * (pause: BOOLEAN);
  324. BEGIN
  325.   IF pause THEN
  326.     aus.StopAudio(mainIO);
  327.   ELSE
  328.     aus.StartAudio(mainIO);
  329.   END;
  330. END PauseSound;
  331. (* \\\ ------------------------------------------------------------------------- *)
  332.  
  333. (* /// -------------------------- "TYPE IMAADPCMData" -------------------------- *)
  334. TYPE    IMAADPCMDataPtr=UNTRACED POINTER TO IMAADPCMData;
  335.         IMAADPCMData=STRUCT (common: CommonData)
  336.         END;
  337.  
  338. VAR     imaAdpcmData: IMAADPCMDataPtr;
  339. (* \\\ ------------------------------------------------------------------------- *)
  340.  
  341. (* /// --------------------- "PROCEDURE DecodeIMAADPCM4()" --------------------- *)
  342. PROCEDURE DecodeIMAADPCM4Mono {"_DecodeIMAADPCM4Mono"} (from{8}: e.APTR;
  343.                                                         toL{9}: e.APTR;
  344.                                                         toR{10}: e.APTR;
  345.                                                         size{0}: LONGINT;
  346.                                                         spec{11}: CommonDataPtr): LONGINT;
  347.  
  348. PROCEDURE DecodeIMAADPCM4Stereo {"_DecodeIMAADPCM4Stereo"} (from{8}: e.APTR;
  349.                                                             toL{9}: e.APTR;
  350.                                                             toR{10}: e.APTR;
  351.                                                             size{0}: LONGINT;
  352.                                                             spec{11}: CommonDataPtr): LONGINT;
  353.  
  354. PROCEDURE SetupIMAADPCM4(VAR codec: CodecHeader);
  355. BEGIN
  356.   IF imaAdpcmData=NIL THEN NEW(imaAdpcmData); END;
  357.   IF codec.stereo THEN
  358.     codec.decoder:=DecodeIMAADPCM4Stereo;
  359.   ELSE
  360.     codec.decoder:=DecodeIMAADPCM4Mono;
  361.   END;
  362.   codec.realCompression:=TRUE;
  363.   codec.compressFactor:=1/4;
  364.   codec.special:=imaAdpcmData
  365. END SetupIMAADPCM4;
  366. (* \\\ ------------------------------------------------------------------------- *)
  367.  
  368. (* /// ---------------------------- "TYPE MACEData" ---------------------------- *)
  369. TYPE    MACEDataPtr=UNTRACED POINTER TO MACEData;
  370.         MACEData=STRUCT (common: CommonData)
  371.         END;
  372.  
  373. VAR     maceData: MACEDataPtr;
  374. (* \\\ ------------------------------------------------------------------------- *)
  375.  
  376. (* /// ----------------------- "PROCEDURE SetupMACE3()" ------------------------ *)
  377. PROCEDURE DecodeMACE3Mono {"_DecodeMACE3Mono"} (from{8}: e.APTR;
  378.                                                 toL{9}: e.APTR;
  379.                                                 toR{10}: e.APTR;
  380.                                                 size{0}: LONGINT;
  381.                                                 spec{11}: CommonDataPtr): LONGINT;
  382.  
  383. PROCEDURE DecodeMACE3Stereo {"_DecodePCM8Stereo"} (from{8}: e.APTR;
  384.                                                    toL{9}: e.APTR;
  385.                                                    toR{10}: e.APTR;
  386.                                                    size{0}: LONGINT;
  387.                                                    spec{11}: CommonDataPtr): LONGINT;
  388.  
  389. PROCEDURE SetupMACE3(VAR codec: CodecHeader);
  390. BEGIN
  391.   IF maceData=NIL THEN NEW(maceData); END;
  392.   IF codec.stereo THEN
  393.     codec.decoder:=DecodeMACE3Stereo;
  394.   ELSE
  395.     codec.decoder:=DecodeMACE3Mono;
  396.   END;
  397.   codec.realCompression:=TRUE;
  398.   codec.compressFactor:=1/3;
  399.   codec.special:=maceData;
  400. END SetupMACE3;
  401. (* \\\ ------------------------------------------------------------------------- *)
  402.  
  403. (* /// ----------------------- "PROCEDURE SetupMACE6()" ------------------------ *)
  404. PROCEDURE DecodeMACE6Mono {"_DecodeMACE6Mono"} (from{8}: e.APTR;
  405.                                                 toL{9}: e.APTR;
  406.                                                 toR{10}: e.APTR;
  407.                                                 size{0}: LONGINT;
  408.                                                 spec{11}: CommonDataPtr): LONGINT;
  409.  
  410. PROCEDURE DecodeMACE6Stereo {"_DecodeMACE6Stereo"} (from{8}: e.APTR;
  411.                                                     toL{9}: e.APTR;
  412.                                                     toR{10}: e.APTR;
  413.                                                     size{0}: LONGINT;
  414.                                                     spec{11}: CommonDataPtr): LONGINT;
  415.  
  416. PROCEDURE SetupMACE6(VAR codec: CodecHeader);
  417. BEGIN
  418.   IF maceData=NIL THEN NEW(maceData); END;
  419.   IF codec.stereo THEN
  420.     codec.decoder:=DecodeMACE6Stereo;
  421.   ELSE
  422.     codec.decoder:=DecodeMACE6Mono;
  423.   END;
  424.   codec.realCompression:=TRUE;
  425.   codec.compressFactor:=1/6;
  426.   codec.special:=maceData;
  427. END SetupMACE6;
  428. (* \\\ ------------------------------------------------------------------------- *)
  429.  
  430. (* /// ---------------------------- "TYPE PCMData" ----------------------------- *)
  431. TYPE    PCMDataPtr=UNTRACED POINTER TO PCMData;
  432.         PCMData=STRUCT (common: CommonData)
  433.         END;
  434.  
  435. VAR     pcmData: PCMDataPtr;
  436. (* \\\ ------------------------------------------------------------------------- *)
  437.  
  438. (* /// ----------------------- "PROCEDURE DecodePCM8()" ------------------------ *)
  439. PROCEDURE DecodePCM8Mono {"_DecodePCM8Mono"} (from{8}: e.APTR;
  440.                                               toL{9}: e.APTR;
  441.                                               toR{10}: e.APTR;
  442.                                               size{0}: LONGINT;
  443.                                               spec{11}: CommonDataPtr): LONGINT;
  444.  
  445. PROCEDURE DecodePCM8Stereo {"_DecodePCM8Stereo"} (from{8}: e.APTR;
  446.                                                   toL{9}: e.APTR;
  447.                                                   toR{10}: e.APTR;
  448.                                                   size{0}: LONGINT;
  449.                                                   spec{11}: CommonDataPtr): LONGINT;
  450.  
  451. PROCEDURE SetupPCM8(VAR codec: CodecHeader);
  452. BEGIN
  453.   IF pcmData=NIL THEN NEW(pcmData); END;
  454.   IF codec.stereo THEN
  455.     codec.decoder:=DecodePCM8Stereo;
  456.   ELSE
  457.     codec.decoder:=DecodePCM8Mono;
  458.   END;
  459.   codec.realCompression:=FALSE;
  460.   codec.compressFactor:=1;
  461.   codec.special:=pcmData;
  462. END SetupPCM8;
  463. (* \\\ ------------------------------------------------------------------------- *)
  464.  
  465. (* /// ----------------------- "PROCEDURE DecodePCM16()" ----------------------- *)
  466. PROCEDURE DecodePCM16Mono {"_DecodePCM16Mono"} (from{8}: e.APTR;
  467.                                                 toL{9}: e.APTR;
  468.                                                 toR{10}: e.APTR;
  469.                                                 size{0}: LONGINT;
  470.                                                 spec{11}: CommonDataPtr): LONGINT;
  471.  
  472.  
  473. PROCEDURE DecodePCM16Stereo {"_DecodePCM16Stereo"} (from{8}: e.APTR;
  474.                                                     toL{9}: e.APTR;
  475.                                                     toR{10}: e.APTR;
  476.                                                     size{0}: LONGINT;
  477.                                                     spec{11}: CommonDataPtr): LONGINT;
  478.  
  479. PROCEDURE SetupPCM16(VAR codec: CodecHeader);
  480. BEGIN
  481.   IF pcmData=NIL THEN NEW(pcmData); END;
  482.   IF codec.stereo THEN
  483.     codec.decoder:=DecodePCM16Stereo;
  484.   ELSE
  485.     codec.decoder:=DecodePCM16Mono;
  486.   END;
  487.   codec.realCompression:=FALSE;
  488.   codec.compressFactor:=1;
  489.   codec.special:=pcmData;
  490. END SetupPCM16;
  491. (* \\\ ------------------------------------------------------------------------- *)
  492.  
  493. (* /// ---------------------------- "TYPE TWOSData" ---------------------------- *)
  494. TYPE    TWOSDataPtr=UNTRACED POINTER TO TWOSData;
  495.         TWOSData=STRUCT (common: CommonData)
  496.         END;
  497.  
  498. VAR     twosData: TWOSDataPtr;
  499. (* \\\ ------------------------------------------------------------------------- *)
  500.  
  501. (* /// ----------------------- "PROCEDURE DecodeTWOS8()" ----------------------- *)
  502. PROCEDURE DecodeTWOS8Mono {"_DecodeTWOS8Mono"} (from{8}: e.APTR;
  503.                                                 toL{9}: e.APTR;
  504.                                                 toR{10}: e.APTR;
  505.                                                 size{0}: LONGINT;
  506.                                                 spec{11}: CommonDataPtr): LONGINT;
  507.  
  508. PROCEDURE DecodeTWOS8Stereo {"_DecodeTWOS8Stereo"} (from{8}: e.APTR;
  509.                                                     toL{9}: e.APTR;
  510.                                                     toR{10}: e.APTR;
  511.                                                     size{0}: LONGINT;
  512.                                                     spec{11}: CommonDataPtr): LONGINT;
  513.  
  514. PROCEDURE SetupTWOS8(VAR codec: CodecHeader);
  515. BEGIN
  516.   IF twosData=NIL THEN NEW(twosData); END;
  517.   IF codec.stereo THEN
  518.     codec.decoder:=DecodeTWOS8Stereo;
  519.   ELSE
  520.     codec.decoder:=DecodeTWOS8Mono;
  521.   END;
  522.   codec.realCompression:=FALSE;
  523.   codec.compressFactor:=1;
  524.   codec.special:=twosData;
  525. END SetupTWOS8;
  526. (* \\\ ------------------------------------------------------------------------- *)
  527.  
  528. (* /// ---------------------- "PROCEDURE DecodeTWOS16()" ----------------------- *)
  529. PROCEDURE DecodeTWOS16Mono {"_DecodeTWOS16Mono"} (from{8}: e.APTR;
  530.                                                   toL{9}: e.APTR;
  531.                                                   toR{10}: e.APTR;
  532.                                                   size{0}: LONGINT;
  533.                                                   spec{11}: CommonDataPtr): LONGINT;
  534.  
  535. PROCEDURE DecodeTWOS16Stereo {"_DecodeTWOS16Stereo"} (from{8}: e.APTR;
  536.                                                       toL{9}: e.APTR;
  537.                                                       toR{10}: e.APTR;
  538.                                                       size{0}: LONGINT;
  539.                                                       spec{11}: CommonDataPtr): LONGINT;
  540.  
  541. PROCEDURE SetupTWOS16(VAR codec: CodecHeader);
  542. BEGIN
  543.   IF twosData=NIL THEN NEW(twosData); END;
  544.   IF codec.stereo THEN
  545.     codec.decoder:=DecodeTWOS16Stereo;
  546.   ELSE
  547.     codec.decoder:=DecodeTWOS16Mono;
  548.   END;
  549.   codec.realCompression:=FALSE;
  550.   codec.compressFactor:=1;
  551.   codec.special:=twosData;
  552. END SetupTWOS16;
  553. (* \\\ ------------------------------------------------------------------------- *)
  554.  
  555. (* /// ----------------------- "PROCEDURE CodecQuery()" ------------------------ *)
  556. PROCEDURE CodecQuery * (VAR codec: CodecHeader): LONGINT;
  557.  
  558. VAR     ret: LONGINT;
  559.  
  560. BEGIN
  561.   ret:=codecSupported;
  562.   codec.stereo:=(codec.channels>1);
  563.   CASE codec.compression OF
  564.   | idima4:
  565.       codec.description:="IMA ADPCM";
  566.       IF codec.bits=16 THEN
  567.         SetupIMAADPCM4(codec);
  568.       ELSE
  569.         ret:=codecUnsupported;
  570.       END;
  571.   | idMAC3:
  572.       codec.description:="MACE 3:1";
  573.       IF codec.bits=8 THEN
  574.         SetupMACE3(codec);
  575.       ELSE
  576.         ret:=codecUnsupported;
  577.       END;
  578.   | idMAC6:
  579.       codec.description:="MACE 6:1";
  580.       IF codec.bits=8 THEN
  581.         SetupMACE6(codec);
  582.       ELSE
  583.         ret:=codecUnsupported;
  584.       END;
  585.   | idraw,
  586.     idraw0:
  587.       IF codec.compression=idraw THEN
  588.         codec.description:="PCM";
  589.       ELSE
  590.         codec.description:="PCM0";
  591.       END;
  592.       IF codec.bits=8 THEN
  593.         SetupPCM8(codec);
  594.       ELSIF codec.bits=16 THEN
  595.         SetupTWOS16(codec);
  596.         (* SetupPCM16(codec); *)
  597.       ELSE
  598.         ret:=codecUnsupported;
  599.       END;
  600.   | idtwos:
  601.       codec.description:="TWOS";
  602.       IF codec.bits=8 THEN
  603.         SetupTWOS8(codec);
  604.       ELSIF codec.bits=16 THEN
  605.         SetupTWOS16(codec);
  606.       ELSE
  607.         ret:=codecUnsupported;
  608.       END;
  609.   | idulaw:
  610.       codec.description:="µ-Law";
  611.       ret:=codecUnsupported;
  612.   ELSE
  613.     codec.description:="unknown";
  614.     ret:=codecUnknown;
  615.   END;
  616.   RETURN ret;
  617. END CodecQuery;
  618. (* \\\ ------------------------------------------------------------------------- *)
  619.  
  620. (* /// ---------------------- "PROCEDURE CheckAudioDMA()" ---------------------- *)
  621. PROCEDURE CheckAudioDMA(codec: CodecHeader): LONGINT;
  622.  
  623. VAR     freq: LONGINT;
  624.  
  625. BEGIN
  626.   freq:=codec.frequency;
  627.   IF (freq>27000) & ~v.doubleScanned THEN
  628. (* /// "$IF RUNDEBUG" *)
  629.     IF o.debug THEN d.PrintF("resampling enabled\n"); END;
  630. (* \\\ $END *)
  631.     codec.special.downScale:=TRUE;
  632.     freq:=freq DIV 2;
  633.   ELSE
  634. (* /// "$IF RUNDEBUG" *)
  635.     IF o.debug THEN d.PrintF("no resampling necessary\n"); END;
  636. (* \\\ $END *)
  637.     codec.special.downScale:=FALSE;
  638.   END;
  639.   RETURN freq;
  640. END CheckAudioDMA;
  641. (* \\\ ------------------------------------------------------------------------- *)
  642.  
  643. (* /// ---------------------- "PROCEDURE InitAudioFile()" ---------------------- *)
  644. PROCEDURE InitAudioFile * (name: ARRAY OF CHAR): BOOLEAN; (* $CopyArrays- *)
  645. BEGIN
  646.   RETURN io.Open(audioFile,name,o.bufferSize,FALSE);
  647. END InitAudioFile;
  648. (* \\\ ------------------------------------------------------------------------- *)
  649.  
  650. (* /// ----------------------- "PROCEDURE DecodeFrame()" ----------------------- *)
  651. PROCEDURE DecodeFrame * (offset: LONGINT;
  652.                          size: LONGINT;
  653.                          offset2: LONGINT;
  654.                          size2: LONGINT;
  655.                          codec: LONGINT);
  656.  
  657. VAR     node: SampleNodePtr;
  658.         decSize: LONGINT;
  659.  
  660. BEGIN
  661.   IF codec#currentCodec THEN
  662.     decoderProc:=codecs[codec].decoder;
  663.     decoderSpec:=codecs[codec].special;
  664.     audioFreq:=CheckAudioDMA(codecs[codec]);
  665.     stereo:=codecs[codec].stereo;
  666.     currentCodec:=codec;
  667.   END;
  668.   IF size2=-1 THEN size2:=size; END;
  669.   size:=mu.min(size,size2)*audioSizeScale;
  670.   IF (size>1) & (size<=audioBufferSize) THEN
  671.     io.SeekTo(audioFile,offset);
  672.     io.Read(audioFile,mainData,size);
  673.     (* y.SETREG(0,d.Write(fh,mainData^,size DIV 3)); *)
  674.     NEW(node);
  675.     decSize:=i2m.Round(size,e.blockSize);
  676.     ol.New(node.dataL,decSize);
  677.     IF stereo OR splittedStereo THEN ol.New(node.dataR,decSize); END;
  678.     decSize:=decoderProc(mainData,node.dataL,node.dataR,size,decoderSpec);
  679.     IF splittedStereo THEN
  680.       io.SeekTo(audioFile,offset2);
  681.       io.Read(audioFile,mainData,size);
  682.       decSize:=decoderProc(mainData,node.dataR,NIL,size,decoderSpec);
  683.     END;
  684.     (* d.PrintF("%ld -> %ld\n",size DIV 3,decSize); *)
  685.     node.freq:=audioFreq;
  686.     node.size:=decSize;
  687.     node.done:=0;
  688.     (* node.id:=u.GetUniqueID(); *)
  689.     e.AddTail(sampleQueue,node);
  690.   ELSE
  691.     d.PrintF("shit\n");
  692.   END;
  693. END DecodeFrame;
  694. (* \\\ ------------------------------------------------------------------------- *)
  695.  
  696. (* /// -------------------- "PROCEDURE DecodeDummyFrame()" --------------------- *)
  697. PROCEDURE DecodeDummyFrame * (size: LONGINT);
  698.  
  699. VAR     node: SampleNodePtr;
  700.         decSize: LONGINT;
  701.  
  702. BEGIN
  703.   REPEAT
  704.     NEW(node);
  705.     decSize:=mu.min(size,audioBufferSize);
  706.     ol.New(node.dataL,decSize);
  707.     IF stereo OR splittedStereo THEN ol.New(node.dataR,decSize); END;
  708.     node.freq:=audioFreq;
  709.     node.size:=decSize;
  710.     node.done:=0;
  711.     (* node.id:=u.GetUniqueID(); *)
  712.     e.AddTail(sampleQueue,node);
  713.     DEC(size,decSize);
  714.   UNTIL size<=0;
  715. END DecodeDummyFrame;
  716. (* \\\ ------------------------------------------------------------------------- *)
  717.  
  718. (* /// ---------------------- "PROCEDURE AllocBuffers()" ----------------------- *)
  719. PROCEDURE AllocBuffers * (): BOOLEAN;
  720.  
  721. VAR     track: g.TrackPtr;
  722.         desc: g.SoundDescriptionPtr;
  723.         codec: CodecHeader;
  724.         cnt: LONGINT;
  725.         cur: LONGINT;
  726.         ret: BOOLEAN;
  727.  
  728. BEGIN
  729.   ret:=TRUE;
  730.   track:=g.animInfo.audioTracks.head;
  731.   DISPOSE(codecs);
  732.   IF es.ListEmpty(g.animInfo.audioTracks) THEN RETURN FALSE; END;
  733.  
  734.   codecCnt:=cu.CalcDescEntries(g.animInfo.audioTracks);
  735.   ol.New(codecs,codecCnt*SIZE(CodecHeader));
  736.   cur:=0;
  737.   WHILE track.node.succ#NIL DO
  738.     FOR cnt:=0 TO track.descriptionEntries-1 DO
  739.       desc:=y.VAL(g.SoundDescriptionPtr,track.descriptions[cnt]);
  740.       codec.compression:=desc.head.dataFormat;
  741.       codec.bits:=desc.sampleSize;
  742.       codec.channels:=desc.channels;
  743.       codec.frequency:=fp.FP32toINT(desc.sampleRate);
  744.  
  745.       CASE CodecQuery(codec) OF
  746.       | codecUnsupported:
  747.           d.PrintF("  Unsupported audio encoding: %s, %ld bits, %ld channels\n",y.ADR(codec.description),
  748.                                                                                 codec.bits,
  749.                                                                                 codec.channels);
  750.           IF ~o.noSound THEN d.PrintF("Continuing without sound\n"); END;
  751.           ret:=FALSE;
  752.       | codecUnknown:
  753.           d.PrintF("  Unknown audio encoding: $%08lx, %ld bits, %ld channels\n",codec.compression,
  754.                                                                                 codec.bits,
  755.                                                                                 codec.channels);
  756.           IF ~o.noSound THEN d.PrintF("Continuing without sound\n"); END;
  757.           ret:=FALSE;
  758.       ELSE
  759.         IF ~o.quiet THEN
  760.           IF codec.stereo THEN
  761.             d.PrintF("  Audio: %s %ld bit Stereo, %lD Hz\n",y.ADR(codec.description),
  762.                                                             codec.bits,
  763.                                                             codec.frequency);
  764.           ELSE
  765.             d.PrintF("  Audio: %s %ld bit Mono, %lD Hz\n",y.ADR(codec.description),
  766.                                                           codec.bits,
  767.                                                           codec.frequency);
  768.           END;
  769.         END;
  770.       END;
  771.       codecs[cur]:=codec;
  772.       INC(cur);
  773.     END;
  774.     audioSizeScale:=1;
  775.     IF (codec.bits=16) & ~codec.realCompression THEN audioSizeScale:=audioSizeScale*2; END; (* kein special => keine Kompression, nur Kodierung *)
  776.     IF codec.stereo THEN audioSizeScale:=audioSizeScale*2; END;
  777.     track:=track.node.succ;
  778.   END;
  779.  
  780.   IF ret & ~o.noSound THEN
  781.     audioBufferSize:=i2m.Round(cu.CalcMaxSize(g.animInfo.audioTracks,FALSE)*audioSizeScale,e.blockSize);
  782.     DISPOSE(mainData);
  783.     audioBufferSize:=mu.max(audioBufferSize,codecs[0].frequency);
  784.     audioBufferSize:=mu.min(audioBufferSize,maxAudioHWSize);
  785.     ol.New(mainData,audioBufferSize);
  786.     INCL(ol.MemReqs,e.chip);
  787.     stereo:=codecs[0].stereo;
  788.     splittedStereo:=(codecCnt=2) & ~stereo;
  789.     (* alte Position von "audioBufferSize:=mu.min(audioBufferSize,maxAudioHWSize);" *)
  790.     FOR cnt:=0 TO 1 DO
  791.       DISPOSE(leftData[cnt]);
  792.       DISPOSE(rightData[cnt]);
  793.       ol.New(leftData[cnt],audioBufferSize);
  794.       IF stereo OR splittedStereo THEN ol.New(rightData[cnt],audioBufferSize); END;
  795.     END;
  796.     EXCL(ol.MemReqs,e.chip);
  797.     currentCodec:=-1;
  798.     audioSigs:=LONGSET{};
  799.     audioFreq:=codecs[0].frequency;
  800.     stereo:=codecs[0].stereo;
  801.   END;
  802.   es.NewList(sampleQueue);
  803.  
  804.   RETURN ret;
  805. END AllocBuffers;
  806. (* \\\ --------------------------------- *)
  807.  
  808. BEGIN
  809.   OpenAudio();
  810.   (* fh:=d.Open("sd0:x",d.newFile); *)
  811. CLOSE
  812.   CloseAudio();
  813.   io.Close(audioFile);
  814.   (* d.OldClose(fh); *)
  815. END CyberQTAudio.
  816.